package com.macro.mall.demo.design.pattern.strategy;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
public class StrategyRegistrar implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        registerStrategies();
    }

    @PostConstruct
    private void registerStrategies() {
        // 扫描带有特定注解的类
        Set<Class<?>> classes = scanForClassesAnnotatedWith("com.macro.mall.demo.design.pattern.strategy", StrategyRealization.class);

        for (Class<?> clazz : classes) {
            // 获取策略接口
            Class<?> strategyInterface = getStrategyInterface(clazz);
            if (strategyInterface != null) {
                // 获取策略ID
                String strategyId = getStrategyId(clazz);
                if (StringUtils.hasText(strategyId)) {
                    // 从Spring上下文中获取策略实现类的实例
                    Object strategyBean = applicationContext.getBean(clazz);
                    // 注册策略
                    StrategyRegistry.registerStrategyBean(strategyInterface, strategyId, strategyBean);
                }
            }
        }
    }

    private Set<Class<?>> scanForClassesAnnotatedWith(String basePackage, Class<? extends Annotation> annotation) {
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AnnotationTypeFilter(annotation));
        return provider.findCandidateComponents(basePackage).stream()
                .map(beanDefinition -> ClassUtils.resolveClassName(beanDefinition.getBeanClassName(), null))
                .collect(Collectors.toSet());
    }

    private Class<?> getStrategyInterface(Class<?> clazz) {
        // 假设策略实现类实现了唯一的接口
        Class<?>[] interfaces = clazz.getInterfaces();
        return interfaces.length > 0 ? interfaces[0] : null;
    }

    private String getStrategyId(Class<?> clazz) {
        // 假设策略ID是从注解中获取的
        StrategyRealization annotation = clazz.getAnnotation(StrategyRealization.class);
        return annotation != null ? annotation.strategyId() : null;
    }
}
